package com.sikulifang.bank.simulation;

import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Db;
import cn.hutool.db.Entity;
import com.sikulifang.bank.simulation.constant.TableConstants;
import com.sikulifang.bank.simulation.persistence.Bank;
import com.sikulifang.bank.simulation.server.service.IServerHandler;
import com.sikulifang.bank.simulation.server.service.impl.ServerHandlerImpl;
import com.sikulifang.frequency.core.FrequencyContext;
import com.sikulifang.frequency.domain.FrequencyProperties;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.Future;

import static com.sikulifang.bank.simulation.util.IServerHandlerUtils.EXECUTOR_SERVICE;
import static com.sikulifang.bank.simulation.util.IServerHandlerUtils.SERVER_MAP;

/**
 * ClassName CommandLineRunnerImpl
 * Description 加载启动的银行服务端口
 *
 * @author Yat
 * Date 2023/5/30 11:30
 * version 1.0
 */
@Slf4j
@Component
public class CommandLineRunnerImpl implements CommandLineRunner {

    @Resource
    private Db db;
    private ApplicationContext applicationContext;

    @Override
    public void run(String... args) throws Exception {
        Entity bankEntity = Entity.create(TableConstants.BANK_TABLE_NAME).set("status", Boolean.TRUE);
        List<Bank> list = db.find(bankEntity, Bank.class);

        // 状态为生效是端口，自动启动
        for (Bank bank : list) {
            String key = bank.getCode() + bank.getPort();
            IServerHandler handler = new ServerHandlerImpl(bank);
            handler.setApplicationContext(applicationContext);
            try {
                Future<?> future = EXECUTOR_SERVICE.submit(handler::start);
                future.get();
            } catch (Exception e) {
                log.error("启动服务失败：Code：{}  port:{}", bank.getCode(), bank.getPort());
            }
            SERVER_MAP.put(key, handler);
        }

        // 限流
        List<Entity> flowControlList = db.find(Entity.create(TableConstants.CURRENT_LIMITING_TABLE_NAME));

        for (Entity entity : flowControlList) {
            // 银行的code
            String bankCode = StrUtil.split(entity.getStr("bank_name"), StrPool.DASHED).get(0);

            FrequencyContext.createInstance(bankCode, getFrequencyProperties(entity));
        }

        log.info("------------------------SUCCESS-----------------------------------");
    }

    private FrequencyProperties getFrequencyProperties(Entity entity) {
        FrequencyProperties frequencyProperties = new FrequencyProperties();
        frequencyProperties.setMode(entity.get("mode", 4));

        frequencyProperties.setQueryInterval(entity.get("query_interval", 0) == 0);
        frequencyProperties.setQueryDelayTime(entity.getLong("query_delay_time"));
        frequencyProperties.setQueryWaitingTime(entity.getLong("query_waiting_time"));

        frequencyProperties.setTradeInterval(entity.get("trade_interval", 0) == 0);
        frequencyProperties.setTradeDelayTime(entity.getLong("trade_delay_time"));
        frequencyProperties.setTradeWaitingTime(entity.getLong("trade_waiting_time"));

        frequencyProperties.setInterval(entity.get("interval", 0) == 1);
        frequencyProperties.setIntervalTime(entity.getLong("interval_time"));

        return frequencyProperties;
    }


    @Autowired
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

}
